classdef Particles<handle
    %PARTICLES 此处显示有关此类的摘要
    %   此处显示详细说明
    
    properties
        T
        grid
        dt
        colormap
        picture
        v_alpha=0.3
    end

    properties(Hidden)
        alpha=0
    end
    
    methods
        function obj = Particles(grid, dt)
            %PARTICLES 构造此类的实例
            %   此处显示详细说明
            obj.grid = grid;
            obj.T = table( ...
                [],[],[],[],[], ...
                VariableNames={'x', 'y', 'C', 'vx', 'vy'} ...
            );
            obj.colormap = grid.colormap;
            obj.dt = dt;
        end

        function push(obj)
            obj.T.x = obj.T.x + obj.T.vx * obj.dt;
            obj.T.y = obj.T.y + obj.T.vy * obj.dt;
            obj.boundary();
        end

        function boundary(obj)
            ids = obj.T.x >= obj.grid.I;
            obj.T.x(ids) = obj.grid.I * 2 - obj.T.x(ids);
            obj.T.vx(ids) = -obj.T.vx(ids);
            ids = obj.T.x <= 0;
            obj.T.x(ids) = -obj.T.x(ids);
            obj.T.vx(ids) = -obj.T.vx(ids);
            ids = obj.T.y >= obj.grid.J;
            obj.T.y(ids) = obj.grid.J * 2 - obj.T.y(ids);
            obj.T.vy(ids) = -obj.T.vy(ids);
            ids = obj.T.y <= 0;
            obj.T.y(ids) = -obj.T.y(ids);
            obj.T.vy(ids) = -obj.T.vy(ids);
        end
        
        function add_particles(obj, num, color, method, varargin)
            %ADD_PARTICLE 此处显示有关此方法的摘要
            %   此处显示详细说明
            if strcmp(method,'random')
                x = rand([num, 1])*obj.grid.I;
                y = rand([num, 1])*obj.grid.J;
                v = rand([num, 1])/obj.dt;
                vx = v.*sin(rand([num, 1])*2*pi);
                vy = v.*cos(rand([num, 1])*2*pi);
            elseif strcmp(method,'start')
                x = ones(num,1)*obj.grid.start_points(color,1);
                y = ones(num,1)*obj.grid.start_points(color,2);
                v = (0.5+0.5*rand([num, 1]))/obj.dt;
                vx = v.*sin(rand([num, 1])*2*pi);
                vy = v.*cos(rand([num, 1])*2*pi);
            elseif strcmp(method,'sweep')
                alpha0 = [0 -pi/2 pi/2 pi];
                x = ones(num,1)*obj.grid.start_points(color,1);
                y = ones(num,1)*obj.grid.start_points(color,2);
                v = (0.6+0.2*rand([num, 1]))/obj.dt;
                vx = v.*cos(obj.alpha+alpha0(color)+0.05*randn([num,1]));
                vy = v.*sin(obj.alpha+alpha0(color)+0.05*randn([num,1]));
                obj.alpha = obj.alpha + obj.v_alpha * obj.dt;
                if obj.alpha >= pi/2 || obj.alpha <= 0
                    obj.v_alpha = -obj.v_alpha;
                end
            end
            C = color*ones([num,1]);
            obj.T = [obj.T;array2table([x,y,C,vx,vy],"VariableNames",obj.T.Properties.VariableNames)];
        end

        function delete_particles(obj, idxes)
            obj.T(idxes,:) = [];
        end

        function plot_particles(obj)
            figure(1)
            color = obj.colormap(obj.T.C,:);
            hold on
            obj.picture = scatter(obj.T.x,obj.T.y, 5, color, 'filled', 'MarkerEdgeColor','k');
            hold off
            axis equal
            axis off
        end

        function update_particles(obj)
            figure(1)
            color = obj.colormap(obj.T.C,:);
            set(obj.picture, "XData",obj.T.x,"YData",obj.T.y,"CData",color)
            drawnow limitrate nocallbacks
        end

        function l = length(obj)
            l = height(obj.T);
        end
    end
end

